tailwind-mergeを使って Tailwind のCSS Classをマージすると出力されたHTMLにCSS Classが取り除かれる場合の対処法

tailwind-mergeを使って Tailwind のCSS Classをマージすると出力されたHTMLにCSS Classが取り除かれる場合の対処法

tailwind-mergeを使用していると時々CSS ClassをSS Classが取り除かれる場合の対処法です
Clock Icon2024.08.15

こんにちわ。
西田@リテールアプリ共創部マッハチームです

事象

tailwind-mergeを使っていると、時々 tailwind-configに追加したカスタムクラスが消えてしまうことがあります

例を挙げると、例えば以下のように tailwind-config に記述すると、 text-body-md というクラスが使えるようになり、定義されたフォントのスタイルを当てれるようになります

export default {
  theme: {
    extend: {
      fontSize: {
	      "body-md": [
          "19px",
          {
            lineHeight: "24px",
            fontWeight: "300",
          },
        ],
      }
    }
// ...省略

Reactだと以下のようにclass指定ができます

{/* tailwind-configに指定されたスタイルが当たる  */}
<span className="text-body-md">サンプル</span>

この状態でfontの色を指定するのに、 text-red-500 を追加します

<span className="text-red-500 text-body-md">Hello World</span>

この状態でtwMergeを使い

<span className={twMerge("text-red-500 text-body-md")}>Hello World</span>

出力されたHTMLを確認すると text-red-500 がオミットされて出力されます

<span class="text-body-md">Hello World</span>

これは text-body-mdclassがフォントの色指定のためのクラスと認識され、同じフォントの色指定のクラスの text-red-500 と重複してると判定され、先に書かれてる text-red-500 classがオミットされてしまっています

解決策

tailwind-mergeに text-body-mdがフォントサイズのクラスであることを知らせるのに tailwind-mergeのconfigにカスタムクラスの定義を指定します

import { extendTailwindMerge } from "tailwind-merge";

const isFontSize = (value: string) => {
  return /^body-.+$/.test(value);
};

export const twMerge = extendTailwindMerge({
  override: {
    classGroups: {
      "font-size": [{ text: [isFontSize] }],
    },
  },
});

ポイントを説明します

extendTailwindMerge を使って既存のtailwind-mergeのコンフィグをもとに設定を上書きします

import { extendTailwindMerge } from "tailwind-merge";

font-sizeのクラスの判定に使う関数です。class名の一部が渡されるので、それを正規表現で判定しています

const isFontSize = (value: string) => {
  return /^body-.+$/.test(value);
};

configを上書きした、twMerge関数を定義しています。こちらの関数を使うと、カスタムクラスが正しく認識され意図しないclassの上書きがされなくなります

export const twMerge = extendTailwindMerge({
  override: {
    classGroups: {
      "font-size": [{ text: [isFontSize] }],
    },
  },
});

最後に

わかってしまうと簡単に解決できたのですが、解決策に辿り着くまで結構時間がかかったので記事にしました
この記事が誰かの役に立てれば幸いです

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.